package com.xmut.rc.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xmut.rc.common.exception.RCException;
import com.xmut.rc.common.utils.EmailUtil;
import com.xmut.rc.common.utils.JwtUtil;
import com.xmut.rc.entity.SysUser;
import com.xmut.rc.entity.UserRole;
import com.xmut.rc.entity.vo.LoginVo;
import com.xmut.rc.entity.vo.RegisterVo;
import com.xmut.rc.entity.vo.SysUserVo;
import com.xmut.rc.mapper.SysUserMapper;
import com.xmut.rc.service.UserRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmut.rc.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @description: 用户接口实现
 * @author: XS
 * @date: 2022/5/23
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    private static HashMap<String, Integer> countMap = new HashMap<>();

    @Resource
    private UserRoleService userRoleService;

    @Override
    public String login(LoginVo loginVo) {
        if (redisTemplate.hasKey(loginVo.getUsername()) && "freeze".equals(redisTemplate.opsForValue().get(loginVo.getUsername()))) {
            throw new RCException("错误次数超过五次，请稍后重试！");
        }

        //从redis获取前端对应的验证码
        String validateCode = (String) redisTemplate.opsForValue().get(loginVo.getValidateCodeId());
        if (!Objects.equals(validateCode, loginVo.getValidateCode())) {
            throw new RCException("验证码有误");
        }


        String username = loginVo.getUsername();
        String password = loginVo.getPassword();

        //校验参数
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            throw new RCException("账号或密码为空！");
        }
        //获取用户
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        SysUser sysUser = baseMapper.selectOne(queryWrapper);

        //用户是否存在
        if (sysUser == null) {
            throw new RCException("用户不存在！");
        }

        password = SecureUtil.sha256().setSalt(sysUser.getSalt().getBytes()).digestHex(password);
        //校验密码
        if (!sysUser.getPassword().equals(password)) {
            countMap.put(sysUser.getId(), countMap.getOrDefault(sysUser.getId(), 0) + 1);
            if (countMap.get(sysUser.getId()) == 5) {
                countMap.remove(sysUser.getId());
                redisTemplate.opsForValue().set(loginVo.getUsername(), "freeze", 300, TimeUnit.SECONDS);
                throw new RCException("错误次数超过五次，请稍后重试！");
            }
            throw new RCException("账号或密码错误！");
        }

        //判断账号状态
        if (sysUser.getStatus() == 2) {
            throw new RCException("账号已被冻结！");
        }

        //使用JWT生成token字符串
        String token = JwtUtil.getJwtToken(sysUser.getId(), sysUser.getUsername());
        return token;
    }

    @Override
    public boolean register(RegisterVo registerVo) {
        //从redis获取前端对应的验证码
        String validateCode = (String) redisTemplate.opsForValue().get(registerVo.getValidateCodeId());
        if (!Objects.equals(validateCode, registerVo.getValidateCode())) {
            throw new RCException("验证码有误");
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(registerVo, sysUser);
        String salt = UUID.randomUUID().toString();
        String password = SecureUtil.sha256().setSalt(salt.getBytes()).digestHex(sysUser.getPassword());
        sysUser.setPassword(password);
        sysUser.setSalt(salt);
        sysUser.setAvatar("https://img2.baidu.com/it/u=3804069081,3968854353&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500");
        sysUser.setSex(3);
        sysUser.setStatus(1);
        sysUser.setIsDelete(0);
        sysUser.setRole("user");
        this.save(sysUser);
        UserRole userRole = new UserRole();
        userRole.setUserId(sysUser.getId());
        userRole.setRoleId("1513389275466534913");
        userRoleService.save(userRole);
        return true;
    }

    @Override
    public SysUserVo getLoginUserInfo(String userId) {
        SysUser sysUser = baseMapper.selectById(userId);
        SysUserVo sysUserVo = new SysUserVo();
        BeanUtils.copyProperties(sysUser, sysUserVo);
        return sysUserVo;
    }

    @Override
    public SysUser selectByUsername(String username) {
        return baseMapper.selectOne(new QueryWrapper<SysUser>().eq("username", username));
    }

    @Override
    public String generateValidateCode(String validateCodeId) {
        // 验证码生成
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(105, 40, 4, 2);
        // 获取验证码base64编码
        String imageBase64 = shearCaptcha.getImageBase64();
        // 前端uuid对应验证码保存redis
        redisTemplate.opsForValue().set(validateCodeId, shearCaptcha.getCode(), 120, TimeUnit.SECONDS);
        return imageBase64;
    }

    @Override
    public boolean generateEmailValidateCode(String validateCodeId, String targetEmail) {
        String emailValidateCode = RandomUtil.randomString(4);
        EmailUtil.sendEmail(targetEmail, "账号管理系统-邮箱验证码", emailValidateCode);
        redisTemplate.opsForValue().set(validateCodeId, emailValidateCode, 120, TimeUnit.SECONDS);
        return true;
    }

    @Override
    public boolean findPassword(String username, String email) {
        //获取用户
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        SysUser sysUser = baseMapper.selectOne(queryWrapper);
        String key = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(key, username, 600, TimeUnit.SECONDS);
        if (email.equals(sysUser.getEmail())) {
            EmailUtil.sendEmail(email, "找回密码", "http://tencent.xs-service.top:4567/#/resetPassword/" + key);
        } else {
            return false;
        }
        return true;
    }

    @Override
    public boolean resetPassword(String password, String key) {
        if (redisTemplate.hasKey(key)) {
            String username = (String) redisTemplate.opsForValue().get(key);
            SysUser user = this.getOne(new QueryWrapper<SysUser>().eq("username", username));
            String salt = UUID.randomUUID().toString();
            String newPassword = SecureUtil.sha256().setSalt(salt.getBytes()).digestHex(password);
            user.setPassword(newPassword);
            user.setSalt(salt);
            this.updateById(user);
            redisTemplate.delete(key);
        } else {
            return false;
        }
        return true;
    }

    @Override
    public boolean modifyPassword(String id, String oldPassword, String newPassword) {
        // TODO
        return false;
    }
}
